﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LIMS.Service;
using LIMS.Entities;
using Castle.Core.Logging;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;

namespace LIMS.Shared
{
    public class UserManagementPagePresenter : BasePresenter<IUserManagementPageView>
    {
        private IUserManagementPageView view;
        private IUserManagementService userService;
        private IGroupManagementService groupService;
        private ILogger logger;
        /// <summary>
        /// Constructor of UserManagementPagePresenter
        /// </summary>
        /// <param name="view"></param>
        /// <param name="oLogger"></param>
        /// <param name="myService"></param>
        /// <param name="oGroupService"></param>
        public UserManagementPagePresenter(IUserManagementPageView view, ILogger oLogger,
            IUserManagementService myService,
            IGroupManagementService oGroupService)
            : base(view)
        {
            this.view = view;
            this.logger = oLogger;
            this.userService = myService;
            this.groupService = oGroupService;
        }
        /// <summary>
        /// Initializing user view 
        /// </summary>
        /// <returns></returns>
        public bool InitializeView()
        {
            try
            {
                GridViewData temp = view.GridData;
                temp.Criteria.Clear();
                temp.Criteria.Add(new GVEntityData("Status", CriteriaDataType.String, new List<string> { Resource.ACTIVE_STATUS }, CriteriaSearchType.Equals, CriteriaRelationWithSibling.None));                               
                
                GridViewData oGrdData = temp;
                view.Users = userService.GetAllUsersForGrid(ref oGrdData);
                view.GridData = oGrdData;
                return true;
            }
            catch (Exception ex)
            {
                logger.Error("Error while initializing view", ex);
                return false;

            }
        }
        /// <summary>
        /// Save User
        /// </summary>
        /// <param name="newUser"></param>
        /// <returns></returns>
        public bool Save(User newUser)
        {
            try
            {
                bool bIsNewUser = (newUser.Id == 0) ? true : false;
                if (userService.Save(newUser))
                {
                    if (bIsNewUser)
                    {
                        //Try sending registration Email
                        if (!userService.SendUserRegistrationEmails(newUser))
                        {
                            logger.Error("User :" + newUser.UserName + " created successfully but could not send mails");
                        }
                    }
                    return true;
                }
                else
                {
                    logger.Error("Error while saving user" + newUser.UserName.ToString() + " information.");
                    return false;

                }
            }
            catch (Exception ex)
            {
                logger.Error("Error while saving user" + newUser.UserName.ToString() + " information.", ex);
                return false;
            }
        }
        /// <summary>
        /// Delete User / Deactivate User
        /// </summary>
        /// <param name="dUser"></param>
        /// <returns></returns>
        public bool Delete(User dUser)
        {
            dUser.Status = "D";
            return userService.Save(dUser);
        }

        /// <summary>
        /// Edits a product, setter does the trick.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public bool Edit(int index)
        {
            try
            {
                view.CurrentIndex = index;
                return true;
            }
            catch (Exception ex)
            {
                logger.Error("Error occured while editing record. Exception : " + ex.Message, ex);
                return false;
            }
        }


        /// <summary>
        /// Returns list of all group names
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllUserGroups()
        {
            List<string> sGroupList = new List<string>();
            foreach (Group oGroup in groupService.GetAllGroups())
                if (oGroup.Status.Trim().Equals("A"))
                    sGroupList.Add(oGroup.Name);
            return sGroupList;
        }
        /// <summary>
        /// Gets group's ID by group name.
        /// </summary>
        /// <param name="sGroupName"></param>
        /// <returns></returns>
        public int GetGroupIdByGroupName(string sGroupName)
        {
            return groupService.GetGroupIdByGroupName(sGroupName);
        }
        /// <summary>
        /// Get Associated User Groups using UserId
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public List<GroupUserLink> GetAssociatedUserGroupsbyUserId(int Id)
        {
            return groupService.GetAssociatedUserGroupLinksbyUserId(Id);
        }

        /// <summary>
        /// Saves the link
        /// </summary>
        /// <param name="oLink"></param>
        /// <returns></returns>
        public bool SaveUserGroupLink(GroupUserLink oLink)
        {
            return userService.SaveUserGroupLink(oLink);
        }

        /// <summary>
        /// Get Group Name using GroupId
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public string GetGroupNameByGroupId(int Id)
        {
            return groupService.GetGroupNameByGroupId(Id);
        }
        /// <summary>
        /// Delete the link
        /// </summary>
        /// <param name="oLink"></param>
        /// <returns></returns>
        public bool DeleteUserGroupLink(GroupUserLink oLink)
        {
            return userService.DeleteUserGroupLink(oLink);
        }
        /// <summary>
        /// User Group Link using User Group Id
        /// </summary>
        /// <param name="GroupId"></param>
        /// <param name="UserId"></param>
        /// <returns></returns>
        public GroupUserLink UserGroupLinkByUserGroupId(int GroupId, int UserId)
        {
            return userService.GetUserGroupLinkByIDs(UserId, GroupId);
        }
        /// <summary>
        /// Checks if a user name is duplicate in database
        /// </summary>
        /// <param name="sUserName"></param>
        /// <returns></returns>
        public bool IsDuplicateUserName(string sUserName)
        {
            //Check if we have existing user, new user will have Id = 0
            if (view.Users[view.CurrentIndex].Id > 0)
            {
                //Check if user has changed user name, if not, don't check for duplicate.
                if (view.Users[view.CurrentIndex].UserName.ToUpper().Trim() == sUserName.ToUpper().Trim())
                {
                    return false;
                }
            }
            //In rest of the cases perform normal check
            if (userService.GetUserByUserID(sUserName) != null)
                return true;
            else
                return false;
        }

        /// <summary>
        /// Checks if a user name is duplicate in database
        /// </summary>
        /// <param name="sUserName"></param>
        /// <returns></returns>
        public bool IsDuplicateEmailAddress(string sEmail)
        {
            //Check if we have existing user, new user will have Id = 0
            if (view.Users[view.CurrentIndex].Id > 0)
            {
                //Check if user has changed Email, if not, don't check for duplicate.
                if (view.Users[view.CurrentIndex].Email.ToUpper().Trim() == sEmail.ToUpper().Trim())
                {
                    return false;
                }
            }
            //In rest of the cases perform normal check
            if (userService.GetUserByEmailAddress(sEmail) != null)
                return true;
            else
                return false;
        }

        /// <summary>
        /// Flags user for password reset and sends mail.
        /// </summary>
        /// <param name="sUrl"></param>
        /// <returns></returns>
        public bool ResetPasswordRequest(string sUrl)
        {
            sUrl = sUrl + Resource.PAGE_LOGIN;
            return userService.ResetUserPassword(view.Users[view.CurrentIndex], sUrl);
        }
        /// <summary>
        /// Search User By User Name
        /// </summary>
        /// <param name="sUserName"></param>
        /// <returns></returns>
        public void SearchUserByKeyword(string sKeyword)
        {
            try
            {
                view.GridData.Criteria.Clear();
                view.GridData.Criteria.Add(new GVEntityData("FirstName", CriteriaDataType.String, new List<string> { sKeyword }, CriteriaSearchType.Contains, CriteriaRelationWithSibling.Or));
                view.GridData.Criteria.Add(new GVEntityData("LastName", CriteriaDataType.String, new List<string> { sKeyword }, CriteriaSearchType.Contains, CriteriaRelationWithSibling.Or));
                view.GridData.Criteria.Add(new GVEntityData("Email", CriteriaDataType.String, new List<string> { sKeyword }, CriteriaSearchType.Contains, CriteriaRelationWithSibling.Or));
                view.GridData.Criteria.Add(new GVEntityData("UserName", CriteriaDataType.String, new List<string> { sKeyword }, CriteriaSearchType.Contains, CriteriaRelationWithSibling.None));
                //view.GridData.Criteria.Add(new GVEntityData("Status", CriteriaDataType.String, new List<string> { Resource.ACTIVE_STATUS }, CriteriaSearchType.Equals, CriteriaRelationWithSibling.None));
                GridViewData oGrdData = view.GridData;
                List<User> myUsers = userService.GetAllUsersForGrid(ref oGrdData);
                view.GridData = oGrdData;
                view.Users = myUsers;
            }
            catch (Exception ex)
            {
                logger.Error("Error in Searching user using Keyword for :" + sKeyword, ex);
            }
        }


        /// <summary>
        /// Validates page For Customer Section
        /// </summary>
        /// <returns></returns>
        public bool ValidatePage()
        {
            //string sErrorMessage = string.Empty;
            //view.FillPageData();
            //bool IsValidated = Resource.Validate(view.PageData, ref sErrorMessage);
            //if (!IsValidated)
            //    view.ShowMessage(MessageType.Error, sErrorMessage);
            //return IsValidated;
            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sUserName"></param>
        /// <returns></returns>
        public User GetUserByUserName(string sUserName)
        {
            return userService.GetUserByUserID(sUserName);
        }

        public bool ValidateUser(string sUserID, string sPassword, string IPAddress, ref User p_User, ref string message)
        {
            p_User = null;
            try
            {
                //"::1" is loopback address for ipv6
                // IPAddress = IPAddress == "::1" ? "127.0.0.1" : IPAddress;
                bool validUser = false;
                User oUser = userService.GetUserByUserID(sUserID);

                if (oUser != null)
                {
                    if (oUser.Password.Equals(Resource.GenerateSHAPasswordHash(sPassword)))
                    {
                        p_User = oUser;
                        validUser = true;
                    }

                    if (validUser)
                    {
                        if (!oUser.Status.Trim().Equals("A"))
                        {
                            // userService.LogUserActivityLog(view.CurrentUser.Id, "User account inactive(" + view.CurrentUser.UserName + "). IP Address: " + IPAddress);
                            message = "Your account is not active. Please contact administrator for activation.";
                            return false;
                        }
                        return true;
                    }
                    message = "Invalid login details (" + sUserID + ")";
                    return false;
                }
                else
                {
                    message = "Invalid login details (" + sUserID + ")";
                    return false;
                }

            }
            catch (Exception ex)
            {
                message = "Error occured while validating user, please contact administrator";
                logger.Error("Error occured while validating user.", ex);
                return false;

            }
        }

    }
}
